package com.urfresh.sp.traffic.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baidu.disconf.client.common.annotations.DisconfFile;
import com.baidu.disconf.client.common.annotations.DisconfFileItem;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.nio.client.CloseableHttpAsyncClient;
import org.apache.http.impl.nio.client.HttpAsyncClients;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.stream.Collectors;

/**
 * Created by urfresh.mark on 2017/6/16.
 */
@Service("trafficListener")
@DisconfFile(filename = "urfresh_bind_user.properties")
public class TrafficListener {

    protected Logger logger = LoggerFactory.getLogger(TrafficListener.class);

    @Autowired
    JedisPool pool;

    /**
     * 用来判断每个手机最多允许绑定的手机，如果超过这个数，就认为是黄牛
     */
    int allowDeviceUserNum = 3;

    @DisconfFileItem(name = "num")
    public int getAllowDeviceUserNum() {
        return allowDeviceUserNum;
    }

    /**
     * 发现是黄牛之后通知其他系统的地址
     */
    String notifyUrl = "";

    @DisconfFileItem(name = "notifyUrl")
    public String getNotifyUrl() {
        return notifyUrl;
    }

    //接收消息
    public void receiveMessage(String mapMessage) {
        logger.info("TrafficListener = " + mapMessage);

        JSONObject object = JSON.parseObject(mapMessage);

        String mobile = object.getString("userName");
        String idfa = object.getString("idfa");
        String androidId = object.getString("androidId");
        String appId = object.getString("appId");
        String deviceId = "";

        if (StringUtils.isEmpty(idfa) || idfa.equals("00000000-0000-0000-0000-000000000000")) {
            deviceId = androidId;
        } else {
            deviceId = idfa;
        }
        deviceId = StringUtils.isEmpty(deviceId) ? appId : deviceId;

        //用户名为空则不进行判断
        if (StringUtils.isEmpty(mobile)) {
//            logger.info("===============================Mobile is empty===============================");
            return;
        }

        if (StringUtils.isEmpty(deviceId) || deviceId.equals("00000000-0000-0000-0000-000000000000")) {
//            logger.info("===============================DeviceId is empty===============================");
            return;
        }

        /*
        由于最终通过userName（手机号）来查询用户是否为黄牛，因此最终需要把设备维度的数据回写到用户维度上
         */

        /*
        通过用户名的维度查看绑定设备的数量
         */
        byUserName(mobile, deviceId);

        /*
        通过设备的维度查看绑定手机号的数量
         */
        byDeviceId(mobile, deviceId);

        //判断是否为黄牛用户
        List<String> userList = isBindUser(mobile);
        if (userList.size() > allowDeviceUserNum) {
            logger.info("查询到黄牛用户:" + mobile);
            //提交到用户系统
            notifyUserSystem(String.join(",", userList));
        }

    }

    /**
     * 判断是否黄牛用户
     *
     * @param mobile
     * @return
     */
    private List<String> isBindUser(String mobile) {
        try (Jedis jedis = pool.getResource()) {
            String traffic_bind_user = jedis.hget("userName:" + mobile, "traffic_bind_user");
            List<String> ss = JSON.parseArray(traffic_bind_user, String.class);
            return ss;
//            if (StringUtils.isEmpty(traffic_bind_user_num))
//                return false;
//            else {
//                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
//                boolean flag = Integer.parseInt(traffic_bind_user_num) >= allowDeviceUserNum;
//                if(flag)
//                    jedis.sadd("hitUserName:"+dateFormat.format(new Date()),mobile);
//                return flag;
//            }
        }
    }

    /**
     * 通知用户系统
     */
    private void notifyUserSystem(String mobile) {
        //使用异步方式提交http请求到用户系统中
        try (CloseableHttpAsyncClient httpclient = HttpAsyncClients.createDefault()) {
            httpclient.start();
            HttpPost httpPost = new HttpPost(notifyUrl);
            JSONObject object = new JSONObject();
            object.put("mobileList", Arrays.asList(mobile));
            StringEntity stringEntity = new StringEntity(object.toJSONString(), ContentType.APPLICATION_JSON);
            httpPost.setEntity(stringEntity);
            Future<HttpResponse> future = httpclient.execute(httpPost, null);
            HttpResponse response = future.get();
            logger.info("after post,mobile=" + mobile + ",result=" + IOUtils.toString(response.getEntity().getContent()));
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //已绑定设备列表
    private void byDeviceId(String mobile, String deviceId) {
        try (Jedis jedis = pool.getResource()) {
            Map<String, String> trackDate = jedis.hgetAll("device:" + deviceId);

            String traffic_bind_user = trackDate.get("traffic_bind_user");
            List<String> userList = JSON.parseArray(traffic_bind_user, String.class);

            //设备第一次登录
            if (userList == null) {
                userList = new ArrayList<>();
                userList.add(mobile);
                trackDate.put("traffic_bind_user_num", "1");
                trackDate.put("traffic_bind_user", JSON.toJSONString(userList));
                logger.info("设备维度新用户：" + mobile + "，device=" + deviceId);
                jedis.hmset("device:" + deviceId, trackDate);
                //用户的设备列表中不包含当前设备
            } else if (userList.contains(mobile) == false) {
                //把当前号码保存到用户设备的绑定列表中

                userList.add(mobile);
                //查询当前设备的绑定数量
                int trafficNum = Integer.parseInt(trackDate.get("traffic_bind_user_num"));

                trackDate.put("traffic_bind_user_num", String.valueOf(trafficNum++));
                trackDate.put("traffic_bind_user", JSON.toJSONString(userList));

                logger.info("设备维度：多个号码登录一个设备：" + mobile + "，device=" + deviceId);
                jedis.hmset("device:" + deviceId, trackDate);

                rewriteByUserName(jedis, mobile, userList);
            }
        }
    }

    /**
     * 把设备维度的数据回写到用户上
     *
     * @param jedis
     * @param userName
     * @param userList
     */
    private void rewriteByUserName(Jedis jedis, String userName, List<String> userList) {
        for (String u : userList) {
            Map<String, String> trackDate = jedis.hgetAll("userName:" + u);

            //在原有的基础上更新数据
            List<String> trafficBindUser = JSON.parseArray(trackDate.get("traffic_bind_user"), String.class);
            if (trafficBindUser == null)
                trafficBindUser = new ArrayList<>();
            trafficBindUser.addAll(userList);
            //用户名去重
            trafficBindUser = trafficBindUser.stream().distinct().collect(Collectors.toList());
            trackDate.put("traffic_bind_user", JSON.toJSONString(trafficBindUser));

            trackDate.put("traffic_bind_user_num", String.valueOf(trafficBindUser.size()));
            jedis.hmset("userName:" + u, trackDate);
        }
    }

    private void byUserName(String mobile, String deviceId) {
        try (Jedis jedis = pool.getResource()) {
            Map<String, String> trackDate = jedis.hgetAll("userName:" + mobile);
            //已绑定设备列表
            String traffic_bind_device = trackDate.get("traffic_bind_device");
            List<String> devices = JSON.parseArray(traffic_bind_device, String.class);

            //用户第一次登录
            if (devices == null) {
                devices = new ArrayList<>();
                devices.add(deviceId);
                trackDate.put("traffic_bind_device_num", "1");
                trackDate.put("traffic_bind_device", JSON.toJSONString(devices));
                logger.info("用户维度保存新用户：" + mobile + "，device=" + deviceId);
                jedis.hmset("userName:" + mobile, trackDate);
                //用户的设备列表中不包含当前设备
            } else if (devices.contains(deviceId) == false) {
                devices.add(deviceId);
                trackDate.put("traffic_bind_device_num", String.valueOf(Integer.parseInt(trackDate.get("traffic_bind_device_num")) + 1));
                trackDate.put("traffic_bind_device", JSON.toJSONString(devices));

                logger.info("用户维度：登录多个设备：" + mobile + "，device=" + deviceId);
                jedis.hmset("userName:" + mobile, trackDate);
            }
        }
    }

    public static void main(String[] args) {
        String s = "[\"13512107171\"]";
        List<String> ss = JSON.parseArray(s, String.class);
        System.out.println(ss.size());
    }

}
